﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

using System.Xml.Linq;

namespace AgileShare.Framework.SiteProvisioning.Definitions
{
	/// <summary>
	/// The configuration of a field that can be used to add a new field to SharePoint. The DefinitionXml property returns the field in a valid SharePoint XML format.
	/// </summary>
	/// <example>	
	/// FieldDefinition fieldDefinition = new FieldDefinition(new Guid("{F56D2B4F-242A-4169-89F9-F3CA0AB33E8A}"), "MyFieldName", "My Field Display Name", "My Field Description", true, "My Group");
	/// 
	/// SPFieldHelper.AddField(fieldDefinition, list.Fields); // Add to SPList fields
	/// SPFieldHelper.AddField(fieldDefinition, web.Fields); // Add to SPWeb fields
	/// </example>
	public class FieldDefinitionChoice : FieldDefinition
	{
		/// <summary>
		/// Gets or sets a value indicating whether [allow multiple values].
		/// </summary>
		/// <value>
		///   <c>true</c> if [allow multiple values]; otherwise, <c>false</c>.
		/// </value>
		public bool AllowMultipleValues { get; set; }

		/// <summary>
		/// Gets or sets the format.
		/// </summary>
		/// <value>
		/// The format.
		/// </value>
		public FieldFormatChoice Format { get; set; }

		/// <summary>
		/// Gets or sets a value indicating whether [fill in choice].
		/// </summary>
		/// <value>
		///   <c>true</c> if [fill in choice]; otherwise, <c>false</c>.
		/// </value>
		public bool FillInChoice { get; set; }

		/// <summary>
		/// Gets or sets the choices.
		/// </summary>
		/// <value>
		/// The choices.
		/// </value>
		public List<string> Choices { get; set; }

		public FieldDefinitionChoice()
		{
			this.Choices = new List<string>();
			if (this.AllowMultipleValues)
			{
				base.Type = FieldType.MultiChoice;
			}
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="FieldDefinitionChoice"/> class.
		/// </summary>
		/// <param name="id">The id.</param>
		/// <param name="name">The name.</param>
		/// <param name="displayName">The display name.</param>
		/// <param name="description">The description.</param>
		/// <param name="required">if set to <c>true</c> [required].</param>
		/// <param name="group">The group.</param>
		/// <param name="allowMultipleValues">if set to <c>true</c> [allow multiple values].</param>
		/// <param name="format">The format.</param>
		/// <param name="fillInChoice">if set to <c>true</c> [fill in choice].</param>
		/// <param name="choices">The choices.</param>
		public FieldDefinitionChoice(Guid id, string name, string displayName, string description, bool required, string group, bool allowMultipleValues, FieldFormatChoice format, bool fillInChoice, IEnumerable<string> choices, params object[] additionalData) :
			base(id, FieldType.Choice, name, displayName, description, required, group, additionalData)
		{
			this.AllowMultipleValues = allowMultipleValues;
			if (this.AllowMultipleValues)
			{
				base.Type = FieldType.MultiChoice;
			}

			this.Format = format;
			this.FillInChoice = fillInChoice;
			this.Choices = choices.ToList();
		}

		/// <summary>
		/// Gets or sets the type.
		/// </summary>
		/// <value>
		/// The type.
		/// </value>
		public override FieldType Type
		{
			get
			{
				return this.AllowMultipleValues ? FieldType.MultiChoice : FieldType.Choice;
			}
			set { }
		}

		/// <summary>
		/// Gets the definition XML.
		/// </summary>
		public override System.Xml.Linq.XElement DefinitionXml
		{
			get
			{
				base.Type = this.AllowMultipleValues ? FieldType.MultiChoice : FieldType.Choice;
				var field = base.DefinitionXml;

				field.Add(new XAttribute("Format", this.Format));
				field.Add(new XAttribute("FillInChoice", this.FillInChoice.ToString().ToUpper()));

				AddChoices(this.Choices, field);

				return field;
			}
		}

		private static void AddChoices(IEnumerable<string> choices, XElement field)
		{
			if (choices.Any())
			{
				field.Add(new XElement("Default"));
				XElement choicesElement = new XElement("CHOICES");
				foreach (string choice in choices)
				{
					choicesElement.Add(new XElement("CHOICE", choice));
				}
				field.Add(choicesElement);
			}
		}
	}
}
